package com.sdd.rpi_mobile.eventRss;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;

/**
 * Asynchronous class for downloading, parsing and creating a list RSSItem 
 * objects in a background thread using a URL
 */
public class FeedDisplay extends AsyncTask<String, Void, List<RssItem>> {

	/**
	 * Calls getFeed using the passed in URL as the location of the RSS feed. 
	 * Also is responsible for catching all exceptions 
	 * @see android.os.AsyncTask#doInBackground(Params[])
	 */
	@Override
	protected List<RssItem> doInBackground(String... params)  {
		try {
			return getFeed(params[0]);
		}
		catch(IOException e) {
			Log.e("RSS", "Network error");
    		return new ArrayList<RssItem>();
		}
		catch(XmlPullParserException e) {
			Log.e("RSS", "XML is not correctly formatted");
			return new ArrayList<RssItem>();
		}
	}
	
	/**
	 * Downloads and parse an RSS feed.
	 * @param feedUrl The URL to the XML file of the RSS feed
	 * @return A list of the items in the RSS feed
	 * @throws IOException
	 * @throws XmlPullParserException
	 */
	private static List<RssItem> getFeed(String feedUrl) throws IOException, XmlPullParserException {
		List<RssItem> items = new ArrayList<RssItem>();
    	InputStream in;
    	in = fileDownloader.downloadFile(feedUrl);
    		    	
    	XmlPullParser parser = Xml.newPullParser();	    		    	
    	parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
    	parser.setInput(in,null);
    	parser.nextTag();
    	
    	// Read the XML document
    	while (parser.next() != XmlPullParser.END_TAG) {
    		if (parser.getEventType() == XmlPullParser.START_TAG) {
    			String name = parser.getName();
    			if ( name.equals("item") ) items.add(createItem(parser));
    			else if(name.equals("rss") || name.equals("channel")) continue;
    			else skip(parser);
    		}
    		else continue;
    	}
    	in.close();
	    return items;
	}
	
	/**
	 * Creates a new RSSItem object from XML Parser.
	 * @param parser 
	 * XmlPullParser currently positioned at the start of an item.
	 * @return 
	 * A filled RSSItem object
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private static RssItem createItem(XmlPullParser parser) throws XmlPullParserException, IOException {
		RssItem item = new RssItem();
		while(parser.next() != XmlPullParser.END_TAG) {
			String data = "";
			if(parser.getEventType() == XmlPullParser.START_TAG) {
				String name = parser.getName();
				parser.require(XmlPullParser.START_TAG, null, name);
				while(parser.next() == XmlPullParser.TEXT) data += parser.getText();
				item.setElement(name, data);
			}
			else continue;
		}
		return item;
	}
	
	/**
	 * Skip unwanted artifacts in the RSS feed.
	 * @param parser
	 * Parser located at the start of an unwanted XML tag
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
	    if (parser.getEventType() != XmlPullParser.START_TAG) throw new IllegalStateException();
	    
	    int depth = 1;
	    while (depth != 0) {
	        switch (parser.next()) {
	        case XmlPullParser.END_TAG:
	            depth--;
	            break;
	        case XmlPullParser.START_TAG:
	            depth++;
	            break;
	        }
	    }
	 }
}
